package com.kitbox.hl.meshow.bpm.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.kitbox.hl.meshow.bpm.bean.BPMWorkItem;
import org.apache.log4j.Logger;


public class EntityMappingUtil {
	private static final Logger logger = Logger.getLogger(EntityMappingUtil.class);

	@SuppressWarnings("rawtypes")
	public static void copyProperites(Object target, Object source) {
		if (target == null || source == null) {
			return;
		}
		if (source instanceof Map) {
			copyProperites(target, (Map) source);
		} else {
			List<Field> f = new ArrayList<Field>();
			fetchFields(target.getClass(), f);
			for (int i = 0; i < f.size(); i++) {
				Field field = f.get(i);
				try {
					field.setAccessible(true);
					Field entityField = source.getClass().getDeclaredField(
							field.getName());
					entityField.setAccessible(true);
					field.set(target, entityField.get(source));
				} catch (Exception e) {
					logger.debug(e);
				}
			}
		}
	}

	public static void copyProperites(Object target, Map source) {
		if (target == null || source == null) {
			return;
		}
		Iterator keys = source.keySet().iterator();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			Object value = source.get(key);
			if (value != null) {
				setValue(target, key, value.toString());
			}
		}
	}

	public static void main(String[] args) {
		BPMWorkItem workItem=new BPMWorkItem();
		List<Field> f = new ArrayList<Field>();
		fetchFields(workItem.getClass(), f);
		for (int i = 0; i < f.size(); i++) {
			Field field = f.get(i);
			//System.out.println(field.getName());
		}
	}

	public static void setValue(Object target, String key, String value) {
		List<Field> f = new ArrayList<Field>();
		fetchFields(target.getClass(), f);
		boolean canSetValue = false;
		try {
			for (int i = 0; i < f.size(); i++) {
				Field field = f.get(i);
				//System.out.println(field.getName());
				if (field.getName().equalsIgnoreCase(key)) {
					if (field.getType() == String.class) {
						field.setAccessible(true);
						field.set(target, value);
						canSetValue = true;
					} else if (field.getType() == Integer.class || field.getType() == int.class) {
						field.setAccessible(true);
						if (value != null) {
							if (value.indexOf('.') != -1) {
								logger.debug("Integer value " + value
										+ " contains the dot character.");
							}
							try {
								field.set(target, Integer.valueOf(value));
							} catch (Exception e) {
								field.set(target, Integer.valueOf(Float
										.valueOf(value).intValue()));
							}
						}
						canSetValue = true;
					} else if (field.getType() == Float.class || field.getType() == float.class) {
						field.setAccessible(true);
						if (value != null) {
							field.set(target, Float.valueOf(value));
						}
						canSetValue = true;
					} else if (field.getType() == Double.class || field.getType() == double.class) {
						field.setAccessible(true);
						if (value != null) {
							field.set(target, Double.valueOf(value));
						}
						canSetValue = true;
					} else if (field.getType() == Long.class || field.getType() == long.class) {
						field.setAccessible(true);
						if (value != null) {
							if (value.indexOf('.') != -1) {
								logger.debug("Long value " + value
										+ " contains the dot character.");
							}
							field.set(target, Long.valueOf(Float.valueOf(value)
									.longValue()));
						}
						canSetValue = true;
					} else if (field.getType() == Date.class) {
						field.setAccessible(true);
						if (value != null) {
							SimpleDateFormat format = new SimpleDateFormat(
									"yyyy-MM-dd HH:mm:ss");
							field.set(target, format.parse(value));
						}
						canSetValue = true;
					}
				}
			}
		} catch (Exception e) {
			logger.debug(e);
		}
		if (!canSetValue) {
			logger.debug("set key " + key + " failed.");
		}
	}

	public static void fetchFields(Class objectClass,
								   List<Field> fieldContainer) {
		for (Class<?> clazz = objectClass; clazz != Object.class; clazz = clazz
				.getSuperclass()) {
			try {
				Field[] fields=clazz.getDeclaredFields();
				fieldContainer.addAll(Arrays.asList(fields));
			} catch (Exception e) {
				logger.debug(e);
			}
		}

	}
	
	/** 
     * 对象属性值复制，仅复制指定名称的属性值 
     * @param from 
     * @param to
     * @throws Exception 
     */  
    public static void copyPropertiesInclude(Object from, Object to) throws Exception {  
        Method[] fromMethods = from.getClass().getDeclaredMethods();  
        Method[] toMethods = to.getClass().getDeclaredMethods();  
        Method fromMethod = null, toMethod = null;  
        String fromMethodName = null, toMethodName = null;  
        for (int i = 0; i < fromMethods.length; i++) {  
            fromMethod = fromMethods[i];  
            fromMethodName = fromMethod.getName();  
            if (!fromMethodName.contains("get")) {  
                continue;  
            }
            toMethodName = "set" + fromMethodName.substring(3);  
            toMethod = findMethodByName(toMethods, toMethodName);  
            if (toMethod == null)  {
                continue;  
            }
            Object value = fromMethod.invoke(from, new Object[0]);  
            if(value == null)  {
                continue;  
            }
            //集合类判空处理  
            if(value instanceof Collection) {  
                Collection newValue = (Collection)value;  
                if(newValue.size() <= 0)  {
                    continue;  
                }
            }  
            toMethod.invoke(to, new Object[] {value});  
        }  
    }  
    
    /** 
     * 从方法数组中获取指定名称的方法 
     *  
     * @param methods 
     * @param name 
     * @return 
     */  
    public static Method findMethodByName(Method[] methods, String name) {  
        for (int j = 0; j < methods.length; j++) {  
            if (methods[j].getName().equals(name))  {
                return methods[j];  
            }
        }  
        return null;  
    }  
}
